package com.yingoo.controller;

import com.yingoo.api.DocumentInfo;
import com.yingoo.api.KeyWordFreque;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.*;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * Created by admin on 2017/7/27.
 */
@Controller
@RequestMapping("/")
public class UserController {
    private String prefixHTML = "<font color='red'>";
    private String suffixHTML = "</font>";
    @RequestMapping("/hello")
    public String  helloworld(){
        return "suc";
    }

    @RequestMapping("/")
    public String  index(){
        System.out.println("index");
        return "search";
    }
    @RequestMapping("/search")
    public ModelAndView search(@RequestParam(value = "keyword",required = false)String keyword,
                               @RequestParam(value = "pageNo",required = false,defaultValue = "1")Integer pageNo,
                               ModelAndView  modelAndView ) {
        Integer pageSize = 8;
        Integer totalPage = 0;
        Integer curentPage = pageNo;
        Integer totalCount = 0;
        modelAndView.setViewName("search");
        if(keyword==null)
            return modelAndView;
        System.out.println("keyword:" + keyword);
        String dir = "F://opt/lucene/index";
        IndexSearcher searcher = null;
        TopDocs hits = null;
        IndexReader indexReader = null;
        String[] fields = {"contents"};
        BooleanClause.Occur[] occ={BooleanClause.Occur.MUST};
        try {
            indexReader = IndexReader.open(FSDirectory.open(new File(dir)));
            searcher = new IndexSearcher(indexReader);
        BooleanQuery booleanQuery = new BooleanQuery();
        String[] strQuery = keyword.split(" +");
        for(int i = 0;i<strQuery.length;i++) {
            Term conterm = new Term("contents", strQuery[i]);
            TermQuery cotquery = new TermQuery(conterm);
            booleanQuery.add(cotquery, BooleanClause.Occur.MUST);
            Term titerm = new Term("title", strQuery[i]);
            TermQuery tiquery = new TermQuery(titerm);
            booleanQuery.add(tiquery, BooleanClause.Occur.SHOULD);
        }
        Analyzer analyzer = new IKAnalyzer(false);
        Query query = null;
        query = MultiFieldQueryParser.parse(Version.LUCENE_33,keyword, fields, occ, analyzer);
        if (searcher != null) {
            hits = searcher.search(booleanQuery, pageSize);
        }

        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        List<DocumentInfo> documentInfos = new ArrayList<>();
        if(pageNo<=0)
            curentPage = 1;
            ScoreDoc lastSd = getLastScoreDoc(curentPage, pageSize, booleanQuery, indexSearcher);
            TopDocs tds = searcher.searchAfter(lastSd,booleanQuery, pageSize);
            System.out.println("total2:"+tds.totalHits);
            totalCount = tds.totalHits;
            totalPage = totalCount / pageSize +1;
            if(pageNo>totalPage)
                curentPage = totalPage;
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                String doctitle = doc.get("title");
                String url = doc.get("path");
                DocumentInfo documentInfo = new DocumentInfo();
                documentInfo.setPath(url);
                documentInfo.setCreateTime(doc.get("createtime"));
                String text = doc.get("contents");
                List<KeyWordFreque> wordFreques = new ArrayList<>();
                TermFreqVector[]  termFreqVectors = indexReader.getTermFreqVectors(sd.doc);
                    for( int f = 0;f< termFreqVectors.length;f++) {
                        System.out.println(termFreqVectors[f].getField());
                        int[] freq = termFreqVectors[f].getTermFrequencies();
                        String[] terms = termFreqVectors[f].getTerms();
                        for( String keys : strQuery) {
                            for( int g = 0; g< terms.length;g++) {
                                if(keys.equals(terms[g])) {
                                    KeyWordFreque keyWordFreque = new KeyWordFreque();
                                    keyWordFreque.setKeyword(keys);
                                    keyWordFreque.setFreque(freq[g]);
                                    wordFreques.add(keyWordFreque);
                                }
                            }
                        }
                    }
                SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(prefixHTML, suffixHTML);
                Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(booleanQuery));
                String highLightText = highlighter.getBestFragment(analyzer, "contents", text);
                String titleHight = highlighter.getBestFragment(analyzer, "title", doctitle);
                modelAndView.addObject("wordFreques", wordFreques);
                if(!StringUtils.isEmpty(titleHight)) {
                    documentInfo.setTitle(titleHight);
                }else
                    documentInfo.setTitle(doctitle);
                List<String> bookNames = MyUtil.getBookNamesByMark(text+doctitle);
                documentInfo.setBookNames(bookNames);
                documentInfo.setKeyWordFreque(wordFreques);
                documentInfo.setDate(highLightText);
                documentInfos.add(documentInfo);
            }
            modelAndView.addObject("documentInfos", documentInfos);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidTokenOffsetsException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }finally {
            try {
                indexReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        modelAndView.addObject("totalPage", totalPage);
        modelAndView.addObject("totalCount", totalCount);
        modelAndView.addObject("curentPage", curentPage);
        modelAndView.addObject("keyword", keyword);
        return modelAndView;
    }
    private ScoreDoc getLastScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher searcher) throws IOException {
        if(pageIndex==1)return null;//如果是第一页就返回空
        int num = pageSize*(pageIndex-1);//获取上一页的最后数量
        System.out.println("num:"+num);
        TopDocs tds = searcher.search(query, num);
        System.out.println("num2:"+tds.totalHits);
        int tpage = tds.totalHits / pageSize + 1;
        if(tpage==1)  return null;
        if(pageIndex>tpage)
            pageIndex = tpage;
        num = pageSize*(pageIndex-1);
        return tds.scoreDocs[num-1];
    }
}
